home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP06.ZIP / CHAP06 / POLYLINE / DLLPOLY.CPP next >
C/C++ Source or Header  |  1993-04-14  |  9KB  |  383 lines

  1. /*
  2.  * DLLPOLY.CPP
  3.  * Modifications for Chapter 6
  4.  *
  5.  * Polyline component object used in Schmoo that supports a custom
  6.  * interface IPolyline.  Contains DLL entry code and the component
  7.  * object exports DllGetClassObject and DllCanUnloadNow and the
  8.  * class factory object.
  9.  *
  10.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  11.  *
  12.  * Kraig Brockschmidt, Software Design Engineer
  13.  * Microsoft Systems Developer Relations
  14.  *
  15.  * Internet  :  kraigb@microsoft.com
  16.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  17.  */
  18.  
  19.  
  20. #define INITGUIDS
  21. #include "polyline.h"
  22.  
  23.  
  24. //Count number of objects and number of locks.
  25. ULONG       g_cObj=0;
  26. ULONG       g_cLock=0;
  27.  
  28. //DLL Instance handle
  29. HINSTANCE   hgInst;
  30.  
  31.  
  32. /*
  33.  * LibMain
  34.  *
  35.  * Purpose:
  36.  *  DLL-specific entry point called from LibEntry.
  37.  *
  38.  * Parameters:
  39.  *  hInst           HINSTANCE instance of the DLL.
  40.  *  wDataSeg        WORD segment selector of the DLL's data segment.
  41.  *  wHeapSize       WORD byte count of the heap.
  42.  *  lpCmdLine       LPSTR to command line used to start the module.
  43.  *
  44.  * Return Value:
  45.  *  HANDLE          Instance handle of the DLL.
  46.  *
  47.  */
  48.  
  49. HANDLE FAR PASCAL LibMain(HINSTANCE hInst, WORD wDataSeg
  50.     , WORD cbHeapSize, LPSTR lpCmdLine)
  51.     {
  52.     WNDCLASS    wc;
  53.  
  54.     if (0!=cbHeapSize)
  55.         UnlockData(0);
  56.  
  57.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  58.     wc.hInstance     = hInst;
  59.     wc.cbClsExtra    = 0;
  60.     wc.lpfnWndProc   = PolylineWndProc;
  61.     wc.cbWndExtra    = CBPOLYLINEWNDEXTRA;
  62.     wc.hIcon         = NULL;
  63.     wc.hCursor       = LoadCursor(NULL, IDC_CROSS);
  64.     wc.hbrBackground = NULL;
  65.     wc.lpszMenuName  = NULL;
  66.     wc.lpszClassName = SZCLASSPOLYLINE;
  67.  
  68.     if (!RegisterClass(&wc))
  69.         return 0;
  70.  
  71.     hgInst=hInst;
  72.     return hInst;
  73.     }
  74.  
  75.  
  76.  
  77.  
  78.  
  79. /*
  80.  * WEP
  81.  *
  82.  * Purpose:
  83.  *  Required DLL Exit function.  Does nothing.
  84.  *
  85.  * Parameters:
  86.  *  bSystemExit     BOOL indicating if the system is being shut
  87.  *                  down or the DLL has just been unloaded.
  88.  *
  89.  * Return Value:
  90.  *  void
  91.  *
  92.  */
  93.  
  94. void FAR PASCAL WEP(int bSystemExit)
  95.     {
  96.     return;
  97.     }
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104. /*
  105.  * DllGetClassObject
  106.  *
  107.  * Purpose:
  108.  *  Provides an IClassFactory for a given CLSID that this DLL is
  109.  *  registered to support.  This DLL is placed under the CLSID
  110.  *  in the registration database as the InProcServer.
  111.  *
  112.  * Parameters:
  113.  *  clsID           REFCLSID that identifies the class factory desired.
  114.  *                  Since this parameter is passed this DLL can handle
  115.  *                  any number of objects simply by returning different
  116.  *                  class factories here for different CLSIDs.
  117.  *
  118.  *  riid            REFIID specifying the interface the caller wants
  119.  *                  on the class object, usually IID_ClassFactory.
  120.  *
  121.  *  ppv             LPVOID FAR * in which to return the interface pointer.
  122.  *
  123.  * Return Value:
  124.  *  HRESULT         NOERROR on success, otherwise contains an error SCODE.
  125.  */
  126.  
  127. HRESULT __export FAR PASCAL DllGetClassObject(REFCLSID rclsid, REFIID riid
  128.     , LPVOID FAR *ppv)
  129.     {
  130.     //CHAPTER6MOD
  131.     if (!IsEqualCLSID(rclsid, CLSID_Polyline6))
  132.         return ResultFromScode(E_FAIL);
  133.     //End CHAPTER6MOD
  134.  
  135.     //Check that we can provide the interface
  136.     if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IClassFactory))
  137.         return ResultFromScode(E_NOINTERFACE);
  138.  
  139.     //Return our IClassFactory for Polyline objects
  140.     *ppv=(LPVOID)new CPolylineClassFactory;
  141.  
  142.     if (NULL==*ppv)
  143.         return ResultFromScode(E_OUTOFMEMORY);
  144.  
  145.     //Don't forget to AddRef the object through any interface we return
  146.     ((LPUNKNOWN)*ppv)->AddRef();
  147.  
  148.     return NOERROR;
  149.     }
  150.  
  151.  
  152.  
  153.  
  154.  
  155. /*
  156.  * DllCanUnloadNow
  157.  *
  158.  * Purpose:
  159.  *  Answers if the DLL can be freed, that is, if there are no
  160.  *  references to anything this DLL provides.
  161.  *
  162.  * Parameters:
  163.  *  None
  164.  *
  165.  * Return Value:
  166.  *  BOOL            TRUE if nothing is using us, FALSE otherwise.
  167.  */
  168.  
  169. STDAPI DllCanUnloadNow(void)
  170.     {
  171.     SCODE   sc;
  172.  
  173.     //Our answer is whether there are any object or locks
  174.     sc=(0L==g_cObj && 0==g_cLock) ? S_OK : S_FALSE;
  175.     return ResultFromScode(sc);
  176.     }
  177.  
  178.  
  179.  
  180.  
  181. /*
  182.  * ObjectDestroyed
  183.  *
  184.  * Purpose:
  185.  *  Function for the Polyline object to call when it gets destroyed.
  186.  *  Since we're in a DLL we only track the number of objects here
  187.  *  letting DllCanUnloadNow take care of the rest.
  188.  *
  189.  * Parameters:
  190.  *  None
  191.  *
  192.  * Return Value:
  193.  *  None
  194.  */
  195.  
  196. void FAR PASCAL ObjectDestroyed(void)
  197.     {
  198.     g_cObj--;
  199.     return;
  200.     }
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207. /*
  208.  * CPolylineClassFactory::CPolylineClassFactory
  209.  *
  210.  * Purpose:
  211.  *  Constructor for an object supporting an IClassFactory that
  212.  *  instantiates Polyline objects.
  213.  *
  214.  * Parameters:
  215.  *  None
  216.  */
  217.  
  218. CPolylineClassFactory::CPolylineClassFactory(void)
  219.     {
  220.     m_cRef =0L;
  221.     return;
  222.     }
  223.  
  224.  
  225.  
  226.  
  227.  
  228. /*
  229.  * CPolylineClassFactory::~CPolylineClassFactory
  230.  *
  231.  * Purpose:
  232.  *  Destructor for a CPolylineClassFactory object.  This will be
  233.  *  called when we ::Release the object to a zero reference count.
  234.  */
  235.  
  236. CPolylineClassFactory::~CPolylineClassFactory(void)
  237.     {
  238.     return;
  239.     }
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246. /*
  247.  * CPolylineClassFactory::QueryInterface
  248.  * CPolylineClassFactory::AddRef
  249.  * CPolylineClassFactory::Release
  250.  *
  251.  * Purpose:
  252.  *  IUnknown implementations for this object.
  253.  */
  254.  
  255. STDMETHODIMP CPolylineClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  256.     {
  257.     *ppv=NULL;
  258.  
  259.     //Any interface on this object is the object pointer.
  260.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
  261.         *ppv=(LPVOID)this;
  262.  
  263.     /*
  264.      * If we actually assign an interface to ppv we need to AddRef it
  265.      * since we're returning a new pointer.
  266.      */
  267.     if (NULL!=*ppv)
  268.         {
  269.         ((LPUNKNOWN)*ppv)->AddRef();
  270.         return NOERROR;
  271.         }
  272.  
  273.     return ResultFromScode(E_NOINTERFACE);
  274.     }
  275.  
  276.  
  277. STDMETHODIMP_(ULONG) CPolylineClassFactory::AddRef(void)
  278.     {
  279.     return ++m_cRef;
  280.     }
  281.  
  282.  
  283. STDMETHODIMP_(ULONG) CPolylineClassFactory::Release(void)
  284.     {
  285.     ULONG           cRefT;
  286.  
  287.     cRefT=--m_cRef;
  288.  
  289.     if (0L==m_cRef)
  290.         delete this;
  291.  
  292.     return cRefT;
  293.     }
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301. /*
  302.  * CPolylineClassFactory::CreateInstance
  303.  *
  304.  * Purpose:
  305.  *  Instantiates a Polyline object that supports the IPolyline
  306.  *  and IUnknown interfaces.  If the caller asks for a different
  307.  *  interface than these two then we fail.
  308.  *
  309.  * Parameters:
  310.  *  punkOuter       LPUNKNOWN to the controlling IUnknown if we are
  311.  *                  being used in an aggregation.
  312.  *  riid            REFIID identifying the interface the caller desires
  313.  *                  to have for the new object.
  314.  *  ppvObj          LPVOID FAR * in which to store the desired interface
  315.  *                  pointer for the new object.
  316.  *
  317.  * Return Value:
  318.  *  HRESULT         NOERROR if successful, otherwise contains E_NOINTERFACE
  319.  *                  if we cannot support the requested interface.
  320.  */
  321.  
  322. STDMETHODIMP CPolylineClassFactory::CreateInstance(LPUNKNOWN punkOuter
  323.     , REFIID riid, LPVOID FAR *ppvObj)
  324.     {
  325.     LPCPolyline         pObj;
  326.     HRESULT             hr;
  327.  
  328.     *ppvObj=NULL;
  329.     hr=ResultFromScode(E_OUTOFMEMORY);
  330.  
  331.     //Verify that if there is a controlling unknown it's asking for IUnknown
  332.     if (NULL!=punkOuter && !IsEqualIID(riid, IID_IUnknown))
  333.         return ResultFromScode(E_NOINTERFACE);
  334.  
  335.     //Create the object.  This also creates a window.
  336.     pObj=new CPolyline(punkOuter, ObjectDestroyed, hgInst);
  337.  
  338.     if (NULL==pObj)
  339.         return hr;
  340.  
  341.     if (pObj->FInit())
  342.         hr=pObj->QueryInterface(riid, ppvObj);
  343.  
  344.     //Kill the object if initial creation or FInit failed.
  345.     if (FAILED(hr))
  346.         delete pObj;
  347.     else
  348.         g_cObj++;
  349.  
  350.     return hr;
  351.     }
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358. /*
  359.  * CPolylineClassFactory::LockServer
  360.  *
  361.  * Purpose:
  362.  *  Increments or decrements the lock count of the DLL.  If the lock
  363.  *  count goes to zero and there are no objects, the DLL is allowed
  364.  *  to unload.  See DllCanUnloadNow.